import 'package:sqflite/sqflite.dart';

import 'package:ilive_ihome/model/dtype.dart';

class Setting {
  String path;
  Database db;
  int version;

  Setting() {
    init();
  }

  void reset() async {
    if (db != null) {
      await db.close();
    }

    if (path != null) {
      await deleteDatabase(path);
    }
    init();
  }

  Future<List<ILiveDev>> load() async {
    List<ILiveDev> list = [];
    if (db == null) {
      print('setting load fail, db is null');
      return null;
    }

    String sql = 'SELECT * FROM devices';
    List<Map<String, dynamic>> res = await db.rawQuery(sql);
    for (Map<String, dynamic> map in res) {
      ILiveDev dev = ILiveDev.def();
      print('select -> $map');
      map.forEach((key, val) {
        if (key == 'name') {
          dev.name = val.toString();
        } else if (key == 'mac') {
          dev.mac = val.toString();
        } else if (key == 'status') {
          dev.status = val;
        } else if (key == 'location') {
          dev.location = val.toString();
        } else if (key == 'type') {
          dev.type = ILiveDev.toType(val.toString());
        } else if (key == 'type2') {
          dev.type2 = ILiveDev.toType2(val.toString());
        }
      });

      if (dev.mac != null) {
        print('add to list ${dev.toString()}');
        list.add(dev);
      }
    }
    return list;
  }

//  void save(
//    List<ILiveDev> devices, {
//    String mac,
//    String name,
//    int status,
//    String location,
//  }) async {
//    if (db == null) {
//      print('setting save error db is null');
//      return;
//    }
//
//    for (ILiveDev dev in devices) {
//      if (mac == null || dev.mac == mac) {
//        if (mac != null) {
//          bool update = false;
//          if (name != null && dev.name != name) {
//            dev.name = name;
//            update = true;
//          }
//          if (status != null && dev.status != status) {
//            dev.status = status;
//            update = true;
//          }
//          if (location != null && dev.location != location) {
//            dev.location = location;
//            update = true;
//          }
//
//          if (update == false) {
//            return;
//          }
//        }
//        print('save $dev, $name $status $location');
//
//        String sql;
//        sql = 'UPDATE devices SET name=?,status=?,location=? WHERE mac=?';
//        var args = [dev.name, dev.status, dev.location, dev.mac.toUpperCase()];
//        int count = await db.rawUpdate(sql, args);
//        print('update $count ${dev.toString()}');
//        if (count == 0) {
//          sql = '''INSERT INTO devices
//              (name,mac,status,location,type,type2)
//              VALUES(?,?,?,?,?,?)''';
//          args = [
//            dev.name,
//            dev.mac.toUpperCase(),
//            dev.status,
//            dev.location,
//            dev.type.toString(),
//            dev.type2.toString(),
//          ];
//          print('insert ${dev.toString()}');
//          await db.rawInsert(sql, args);
//        }
//
//        if (mac != null) {
//          return;
//        }
//      }
//    }
//  }

  Future<int> save(ILiveDev dev) async {
    if (db == null) {
      print('setting save error, db is null');
      return Future.value(-1);
    }

    int count = await update(dev);
    if (count <= 0) {
      count = await insert(dev);
    }
    return Future.value(count);
  }

  Future<int> insert(ILiveDev dev) async {
    if (db == null) {
      print('setting insert fail, db is null');
      return Future.value(-1);
    }

    String sql = '''INSERT INTO devices 
      (name,mac,status,location,type,type2)
      VALUES (?,?,?,?,?,?)''';

    var args = [
      dev.name,
      dev.mac.toUpperCase(),
      dev.status,
      dev.location,
      dev.type.toString(),
      dev.type2.toString(),
    ];

    int count = await db.rawInsert(sql, args);
    print('insert $count ${dev.toString()}');
    return Future.value(count);
  }

  Future<int> update(ILiveDev dev) async {
    if (db == null) {
      print('setting update fail, db is null');
      return Future.value(-1);
    }

    String sql = '''UPDATE devices 
      SET name=?,status=?,location=? 
      WHERE mac=?''';

    var args = [
      dev.name,
      dev.status,
      dev.location,
      dev.mac.toUpperCase()
    ];
    int count = await db.rawUpdate(sql, args);
    print('update $count ${dev.toString()}');
    return Future.value(count);
  }

  Future<int> delete(String mac) async {
    if (db == null) {
      print('setting delete fail, db is null');
      return Future.value(null);
    }

    String sql = '''DELETE FROM devices 
      WHERE mac=?''';

    var args = [mac.toUpperCase()];
    int count = await db.rawDelete(sql, args);
    return Future.value(count);
  }

  Future<ILiveDev> query(String mac) async {
    if (db == null) {
      print('setting query fail, db is null');
      return Future.value(null);
    }

    /**
     * mac: the mac is string
     * name: the name is string
     * status: the status 0/1 on/off or disable/enable(work)
     * location: the location is string
     * type: DevType index
     * type2: ILiveDevType index
     * */

    String sql = '''SELECT 
      mac,name,status,location,type,type2 
      FROM devices 
      WHERE mac=?''';

    ILiveDev device;
    var args = [mac.toUpperCase()];
    List<Map<String, dynamic>> res = await db.rawQuery(sql, args);
    for (Map<String, dynamic> map in res) {
      ILiveDev dev = ILiveDev.def();
      print('select -> $map');
      map.forEach((key, val) {
        if (key == 'name') {
          dev.name = val.toString();
        } else if (key == 'mac') {
          dev.mac = val.toString();
        } else if (key == 'status') {
          dev.status = val;
        } else if (key == 'location') {
          dev.location = val.toString();
        } else if (key == 'type') {
          dev.type = ILiveDev.toType(val.toString());
        } else if (key == 'type2') {
          dev.type2 = ILiveDev.toType2(val.toString());
        }
      });

      if (dev.mac != null) {
        device = dev;
        print('query $mac ${dev.toString()}');
      }
    }

    if (device != null) {
      print('query $mac success, ${device.toString()}');
    } else {
      print('query $mac not found');
    }
    return device;
  }

  Future onCreate(Database db, int version) async {
    this.version = version;
    this.db = db;

    /**
     * mac: the mac is string
     * name: the name is string
     * status: the status 0/1 on/off or disable/enable(work)
     * location: the location is string
     * type: DevType index
     * type2: ILiveDevType index
     * */

    String sql = '''CREATE TABLE devices (
      mac TEXT PRIMARY KEY, 
      name TEXT, status INTEGER, 
      location TEXT, 
      type TEXT, 
      type2 TEXT
      )''';
    await db.execute(sql);
  }

  void init() async {
    var path = await getDatabasesPath();
    this.path = '$path/devices.sqlite3';
    version = 1;
    db = await openDatabase(this.path, version: version, onCreate: onCreate);
  }
}
